<!-- AutoNant.xslt - Generate a Nant build file
   - Tamara Roberson <tamara.roberson@gmail.com>
   - RELEASED IN THE PUBLIC DOMAIN -->

<xsl:stylesheet xmlns:xsl="http://www.w3.org/1999/XSL/Transform" version="1.0">
	<xsl:output method="xml" indent="yes" />
	<xsl:variable name="debug">true</xsl:variable>
	<xsl:variable name="has_externals" select="/autonant/externals" />
	<xsl:variable name="has_references" select="/autonant/references" />
	<xsl:variable name="has_packages" select="/autonant/packages" />
	<xsl:variable name="output_type" select="/autonant/output/@type" />
	<xsl:variable name="language" select="/autonant/output/@language" />
	<xsl:variable name="output">
		<xsl:text>${bin.dir}/</xsl:text>
		<xsl:value-of select="/autonant/output" />
	</xsl:variable>

	<!-- MAIN -->
	<xsl:template match="/autonant">
		<project name="{@name}" default="build" basedir=".">
			<!-- Description -->
			<description>
				<xsl:value-of select="description" />
			</description>

			<!-- Properties -->
			<property name="debug"
			  overwrite="false"
			  value="{$debug}" />

			<property
			  name="base.dir"
			  overwrite="false"
			  value="${{project::get-base-directory()}}" />

			<property
			  name="bin.dir"
			  value="${{base.dir}}/bin" />

			<property
			  name="external.dir"
			  value="${{base.dir}}/external" />

			<property
			  name="src.dir"
			  value="${{base.dir}}/src" />

			<property
			  name="filename"
			  overwrite="false"
			  value="default.autonant" />

			<property
			  name="buildfile"
			  value="${{filename}}.build" />

			<property
			  name="buildfile_path"
			  value="${{path::combine (build.dir, buildfile)}}" />

			<property
			  name="external_buildfile"
			  value="${{filename}}-external.build" /> 

			<property
			  name="external_buildfile_path"
			  value="${{path::combine (build.dir, external_buildfile)}}" />

			<!-- Filesets -->
			<xsl:call-template name="fileset-backups" />
			<xsl:call-template name="fileset-sources" />

			<xsl:if test="$has_externals or $has_references">
				<xsl:call-template name="fileset-references" />
			</xsl:if>

			<!-- Targets -->
			<xsl:call-template name="target-build" />
			<xsl:call-template name="target-clean" />
			<xsl:if test="$has_externals">
				<xsl:call-template name="target-clean-external" />
			</xsl:if>
		</project>
	</xsl:template>

	<!-- Fileset-Backups -->
	<xsl:template name="fileset-backups">
		<fileset id="backups" basedir="${{base.dir}}" defaultexcludes="false">
			<include name="**/*~" />
		</fileset>
	</xsl:template>

	<!-- Fileset-Sources -->
	<xsl:template name="fileset-sources">
		<fileset id="sources" basedir="${{src.dir}}">
			<xsl:choose>
				<xsl:when test="$language = 'C#'">
					<include name="*.cs" />
				</xsl:when>
				<xsl:when test="$language = 'boo'">
					<include name="*.boo" />
				</xsl:when>
			</xsl:choose>
		</fileset>
	</xsl:template>

	<!-- Fileset-Externals -->
	<xsl:template name="fileset-externals">
			<xsl:for-each select="externals/module">
				<xsl:element name="include">
					<xsl:attribute name="name">
						<xsl:text>${bin.dir}/</xsl:text>
						<xsl:value-of select="." />
						<xsl:text>.</xsl:text>
						<xsl:value-of select="@type" />
					</xsl:attribute>
				</xsl:element>
			</xsl:for-each>
	</xsl:template>	

	<!-- Fileset-References -->
	<xsl:template name="fileset-references">
		<assemblyfileset id="references">
			<xsl:call-template name="fileset-externals" />
			<xsl:for-each select="references/assembly">
				<include name="{.}" />
			</xsl:for-each>
		</assemblyfileset>
	</xsl:template>

	<!-- Target-Build -->
	<xsl:template name="target-build">
		<target name="build" description="compiles the source code">
			<mkdir dir="${{bin.dir}}" failonerror="false" />
			<xsl:if test="$has_externals">
				<nant target="build" buildfile="${{external_buildfile_path}}" />
			</xsl:if>
			
			<xsl:choose>
				<xsl:when test="$language = 'C#'">
					<xsl:call-template name="target-build-cs" />
				</xsl:when>
				<xsl:when test="$language = 'boo'">
					<xsl:call-template name="target-build-boo" />
				</xsl:when>
			</xsl:choose>
		</target>
	</xsl:template>

	<!-- Pkg-Config -->
	<xsl:template name="pkg-config">
		<xsl:param name="pkg" />

		<property name="tmp" value="${{path::get-temp-file-name()}}" />

		<exec program="pkg-config" output="${{tmp}}">
			<arg value="--libs" />
			<arg value="{$pkg}" />
		</exec>

		<loadfile file="${{tmp}}" property="args-tmp" />
		<delete file="${{tmp}}" />

		<property name="pkg-config-{$pkg}-args" value="${{string::trim (args-tmp)}}" />
	</xsl:template>


	<!-- Target-Build-CS -->
	<xsl:template name="target-build-cs">
		<csc target="{$output_type}" output="{$output}" debug="{$debug}">
			<sources refid="sources" />
			<xsl:if test="$has_externals or $has_references">
				<references refid="references" />
			</xsl:if>
			<xsl:if test="$has_packages">
				<pkg-references>
					<xsl:for-each select="$has_packages">
						<package name="{.}" />
					</xsl:for-each>
				</pkg-references>
			</xsl:if>
		</csc>
	</xsl:template>

	<!-- Target-Build-Boo -->
	<xsl:template name="target-build-boo">
		<loadtasks assembly="${{boo_tasks}}" />

		<xsl:for-each select="$has_packages/pkg">
			<xsl:call-template name="pkg-config">
				<xsl:with-param name="pkg">
					<xsl:value-of select="." />
				</xsl:with-param>
			</xsl:call-template>
		</xsl:for-each>

		<booc target="{$output_type}" output="{$output}">
			<sources refid="sources" />
			<xsl:if test="$has_externals or $has_references">
				<references refid="references" />
			</xsl:if>
			<xsl:for-each select="$has_packages/pkg">
				<arg value="${{pkg-config-{.}-args}}" /> 
			</xsl:for-each>
		</booc>
	</xsl:template>

	<!-- Target-Clean -->
	<xsl:template name="target-clean">
		<target name="clean" description="remove all generated files">
			<xsl:if test="$has_externals">
				<call target="clean-external" />
			</xsl:if>
			<delete dir="${{bin.dir}}" failonerror="false" />
			<delete failonerror="false">
				<fileset refid="backups" />
			</delete>
		</target>
	</xsl:template>

	<!-- Target-Clean-External -->
	<xsl:template name="target-clean-external">
		<target
		  name="clean-external"
		  description="remove all generated files in external assemblies">
				<nant 
				  target="clean"
				  buildfile="${{external_buildfile_path}}" />
		</target>
	</xsl:template>
</xsl:stylesheet>

